package pl.wroc.pwr.docs.repos.webapp.repo;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.tika.Tika;
import org.apache.tika.exception.TikaException;

import org.apache.tika.metadata.Metadata;
import org.apache.tika.parser.AutoDetectParser;
import org.apache.tika.exception.TikaException;
import org.xml.sax.helpers.DefaultHandler;

/**
 * Dokument tekstowy. 
 * Obsługa formatów, kodowania i wyciągania tekstu.
 */
//TODO dodać datę dodania dokumentu
//TODO dodać hash dokumentu, zeby nie dodawać duplikatow

public class Document {
	public enum FORMAT { DOC, DOCX, ODT, PDF, RTF, TXT, OTHER };
	public enum STORAGE_TYPE { FLAT_FILE, DB_FILE }
	private static HashMap<String, FORMAT> TIKA_FORMAT_MAPPING;
	// TODO czy to może być statyczne (przy wielu zapytaniach)??
	private static Tika tika = new Tika();
	//TODO sprawdzić czy to jest wyczerpujaca lista
	static {
		TIKA_FORMAT_MAPPING = new HashMap<String, Document.FORMAT>();
		TIKA_FORMAT_MAPPING.put("application/msword", FORMAT.DOC);
		TIKA_FORMAT_MAPPING.put("application/x-tika-msoffice", FORMAT.DOC);
		TIKA_FORMAT_MAPPING.put("application/vnd.openxmlformats-officedocument.wordprocessingml.document", FORMAT.DOCX);
		TIKA_FORMAT_MAPPING.put("application/x-tika-ooxml", FORMAT.DOCX);
		TIKA_FORMAT_MAPPING.put("application/vnd.oasis.opendocument.text", FORMAT.ODT);
		TIKA_FORMAT_MAPPING.put("application/zip", FORMAT.ODT);
		TIKA_FORMAT_MAPPING.put("application/pdf", FORMAT.PDF);
		TIKA_FORMAT_MAPPING.put("application/rtf",FORMAT.RTF);
		TIKA_FORMAT_MAPPING.put("text/plain", FORMAT.TXT);
	}
	//TODO gdzies to przeniesc, przyspiesza odpowiedz serwera o ok. 150 ms 
	static {
		Logger.getLogger(org.apache.pdfbox.pdfparser.PDFObjectStreamParser.class).setLevel(Level.OFF);
		Logger.getLogger(org.apache.pdfbox.util.PDFStreamEngine.class).setLevel(Level.OFF);
	}
	
	private int id;
	private String filename;
	private FORMAT format;
	private STORAGE_TYPE type;

	public static boolean isDocument(InputStream in) throws IOException {
		String tikaFormat = tika.detect(in);
		return TIKA_FORMAT_MAPPING.containsKey(tikaFormat);
	}
	
	public static FORMAT format(InputStream in) throws IOException{
		String tikaFormat = tika.detect(in);
		System.out.println(tikaFormat);
		FORMAT format = TIKA_FORMAT_MAPPING.get(tikaFormat);
		return format != null ? format : FORMAT.OTHER;
	}
	
	public static String extractContent(InputStream in) throws IOException, TikaException {
		return extractContent(in,-1);
	}
	
	public static String extractContent(InputStream in, int maxStringLength) throws IOException, TikaException {
		tika.setMaxStringLength(maxStringLength);
		return tika.parseToString(in);
	}
	
	public static Metadata extractMetadata(InputStream in) throws Exception {
		Metadata metadata = new Metadata();
		AutoDetectParser parser = new AutoDetectParser();
		parser.parse(in, new DefaultHandler(), metadata);

		return metadata;
	}
		
	public Document(int id, String filename, FORMAT format, STORAGE_TYPE type){
		this.id = id;
		this.filename = filename;
		this.format = format;
		this.type = type;
	}
	
	public int getId(){
		return id;
	}
	
	public String getFilename() {
		return filename;
	}
	
	public FORMAT getFormat() {
		return format;
	}

	public STORAGE_TYPE getType(){
		return type;
	}
}